from django.shortcuts import render
from .serializer import *
from rest_framework.views import APIView
from .models import *
from rest_framework.response import Response
from rest_framework.generics import *
from rest_framework.mixins import *
from rest_framework.viewsets import ModelViewSet
from rest_framework import viewsets
import random, redis,time,json
from .tasks import send_message
from django.contrib.auth.hashers import check_password
from datetime import datetime
from rest_framework_jwt.utils import jwt_payload_handler,jwt_encode_handler
from rest_framework.pagination import PageNumberPagination
# Create your views here.


# 部门
class DepartmentViewSet(ModelViewSet):
    queryset = Department.objects.all()
    serializer_class = DepartmentSer
    lookup_field = "pk"
    lookup_url_kwarg = "pk"

# 部门的视图
# class DepartmentView(ListCreateAPIView):
#     queryset = Department.objects.all()
#     serializer_class = DepartmentSer
#
#     # def get(self, request):
#         # deps = Department.objects.all()
#         # deps = self.get_queryset()
#         # ser = DepartmentSer(deps, many=True)
#         # ser = self.get_serializer()
#
#         # return Response({
#         #     "code": 200,
#         #     "msg": "加载数据成功",
#         #     "data": ser.data
#         # })
#         # return self.list(request)
#
#     # def post(self, request):
#         # name = request.data.get("name")
#         # dep = Department.objects.filter(name=name)
#         # if dep:
#         #     return Response({
#         #         "code": 400,
#         #         "msg": "该部门已存在"
#         #     })
#         # 反序列化
#         # ser = DepartmentSer(data=request.data)
#         # ser = self.get_serializer(data=request.data)
#
#         # 数据校验
#         # if ser.is_valid():      # 底层执行数据校验
#
#             # 存入数据库
#         #     ser.save()
#         #
#         #     return Response({
#         #         "code": 200,
#         #         "msg": "添加部门成功",
#         #         "data": ser.data
#         #     })
#         #
#         # else:
#         #     return ({
#         #         "code": 400,
#         #         "msg": ser.error_messages
#         #     })
#         # return self.post(request)


# 删除一个添加一个修改一个
# class DepartmentDetailView(RetrieveUpdateDestroyAPIView):
#     queryset = Department.objects.all()
#     serializer_class = DepartmentSer
#     lookup_field = "pk"
#     lookup_url_kwarg = "pk"


# class DutySet(APIView):
    # queryset = Department.objects.all()
    # serializer_class = DepartmentSer
    # lookup_field = "pk"
    # lookup_url_kwarg = "pk"

# 部门的视图


# 员工的视图
class DutyAPIView(APIView):
    # queryset = Duty.objects.all()
    # serializer_class = DutySer

    def get(self, request):
        deps = Duty.objects.all()
        # deps = self.get_queryset()
        ser = DutySer(deps, many=True)
        # ser = self.get_serializer()

        return Response({
            "code": 200,
            "msg": "加载数据成功",
            "data": ser.data
        })
        # return self.list(request)

    def post(self, request):
        name = request.data.get("name")
        dep = Duty.objects.filter(name=name)
        if dep:
            return Response({
                "code": 400,
                "msg": "该部门已存在"
            })
        # 反序列化
        ser = DutySer(data=request.data)
        # ser = self.get_serializer(data=request.data)

        # 数据校验
        if ser.is_valid():      # 底层执行数据校验

            # 存入数据库
            ser.save()

            return Response({
                "code": 200,
                "msg": "添加部门成功",
                "data": ser.data
            })

        else:
            return ({
                "code": 400,
                "msg": ser.error_messages
            })
        # return self.post(request)


# 员工的增删改查
class StaffAPIView(viewsets.ViewSet):

    def list(self, request):

        staff = Staff.objects.all()

        staff_ser = StaffSer(staff, many=True)

        return Response({
            "code": 200,
            "msg": "查询员工成功",
            "data": staff_ser.data
        })


    def push_data(self, request):

        name = request.data.get("name")
        sex = request.data.get("sex")
        phone = request.data.get("phone")
        email = request.data.get("email")
        department = request.data.get("department")
        duty = request.data.get("duty")

        staff = Staff.objects.filter(name=name)

        if staff:
            return Response({
                "code": 400,
                "msg": "员工已存在",
            })

        staff_ser = StaffSer(data=request.data)

        if staff_ser.is_valid():

            staff_ser.save()

            return Response({"code": 200, "msg":"添加员工成功"})

        else:
            return Response({"code": 400, "error":staff_ser.error_messages})

    # 获取一个员工信息
    def one_data(self, request, pk):

        staff = Staff.objects.get(id=pk)
        print("数据:",staff)
        ser = StaffSer(staff)

        return Response({"code": 200, "msg": "获取成功","data":ser.data})

    # 删除一个员工
    def delete_data(self,request,pk):

        Staff.objects.filter(id=pk).delete()

        return Response({"code":200, "msg":"删除成功"})

    # 修改一个员工
    def put_data(self, request, pk):
        id = request.data.get("id")
        name = request.data.get('name')
        sex = request.data.get("sex")
        phone = request.data.get("phone")
        email = request.data.get("email")
        department = request.data.get("department")
        duty = request.data.get("duty")
        # 通过dep_id来获取要修改的数据对象
        dep_obj = Staff.objects.filter(id=id).first()
        # 判断对象是否存在
        if dep_obj:
            # 存在时，进行修改
            # instance要修改的对象
            # data 要修改的数据
            # partial=True 默认修改全部，为True时，可以修改部分字段
            staff_ser = StaffSer(instance=dep_obj, data=request.data, partial=True)

            # raise_exception 验证出错时，抛出异常信息
            staff_ser.is_valid(raise_exception=True)
            staff_ser.save()

            # 返回数据
            return Response({'msg': staff_ser.data, 'code': 200})
        else:
            return Response({'msg': '修改的数据不存在', 'code': 400})


# 获取所有员工数据
class StaffListView(GenericAPIView):
    queryset = Staff.objects.all()  # 指定查询集
    serializer_class = StaffSer  # 指定序列化器类

    def get(self, request):
        department_list = self.get_queryset()  # 获取查询集数据
        dep_serializer = self.get_serializer(department_list, many=True)
        return Response(dep_serializer.data)


# 获取单个员工数据
class StaffOne(GenericAPIView):
    queryset = Staff.objects.all()  # 指定查询集
    serializer_class = StaffSer  # 指定序列化器类
    lookup_field = "pk"

    def get(self, request):
        department_list = self.get_object()
        dep_serializer = self.get_serializer(department_list)
        return Response(dep_serializer.data)


# 员工的视图集
class StaffSet(ModelViewSet):
    queryset = Staff.objects.all()
    serializer_class = StaffSer
    lookup_url_kwarg = "pk"
    lookup_field = "pk"


# 查询所有员工数据， 添加一个员工
class StaffCreateView(ListCreateAPIView):
    queryset = Staff.objects.all()
    serializer_class = StaffSet


# 删除一个，查看一个，修改一个员工
class StaffRetrieveUpdateDestroy(RetrieveUpdateDestroyAPIView):
    queryset = Staff.objects.all()
    serializer_class = StaffSet
    lookup_field = "pk"


# 发送短信
class SmsAPIView(APIView):

    def post(self, request):

        # 1.获取前端数据
        mobile = request.data.get("mobile")
        # uuid_ = request.data.get("uuid")

        # 1.5 数据校验
        if not all([mobile,]):
            return Response({
                "code": 400,
                "error": "数据不完整"
            })

        # 2.生成短信验证码
        sms_code = "%d"%random.randint(10000,99999)

        # 2.5 存入短信验证码
        redis_conn = redis.Redis(host="localhost", port=6379, db=3, password="123")
        redis_conn.set(mobile, sms_code, ex=300)

        # 3.请求容联云， 发送短信
        res = send_message.delay(sms_code, mobile)


        # if res:
        #     return Response({"code": 200, "msg": "发送短信成功！"})
        #
        # else:
        #     return Response({"code": 400, "error": "短信发送失败！"})

        return Response({
            "code": 200,
            "msg": '短信已发送，请注意查收！'
        })


# 校验验证码是否正确
class SmsVerifyAPIView(APIView):

    def post(self, request):
        # 1.接受前端数据
        sms_code = request.data.get("sms_code")
        uuid_ = request.data.get("code_id")

        # 2. 查询redis 拿出存储的短信验证码
        redis_conn = redis.Redis(host="localhost", port=6379, db=3, password="123")
        stored_sms_code = redis_conn.get(uuid_)

        # 3.判断
        if stored_sms_code and stored_sms_code.decode() == sms_code:
            return Response({
                "code": 200,
                "msg": "对比成功"
            })
        else:
            return Response({
                "code": 400,
                "error": "对比失败"
            })


# 登录接口的视图
class LoginCountView(APIView):
    def post(self, request):
        # 1.接受前端数据
        username = request.data.get("username")
        password = request.data.get("password")
        mobile = request.data.get("mobile")
        code = request.data.get("code")

        # 2.数据基本校验
        # if not all([username, password, mobile, code]):
        #     return Response({
        #         "code": 400,
        #         "msg": '数据不完整'
        #     })

        # 3.判断用户是否第一次登录
        user = User.objects.filter(username=username).first()
        redis_conn = redis.Redis(host="localhost", port=6379, db=3, password="123")

        if user:
            # 4.用户存在，即需要登录
            # 判断用户的密码
            if check_password(password, user.password):
                # 密码正确, 需要验证是否具有登录该站点的权限
                if user.is_active and user.is_staff:
                    # 具有登录的权限，即登录完成

                    # 生成jwt_token
                    token = self.gen_token(user)
                    user.last_login = datetime.now()
                    user.save()

                    # 获取当前用户所具有的权限
                    # 获取用户所有的角色
                    roles = user.role.all()
                    permissions_list = []
                    for role in roles:
                        # 获取每个角色具有的权限
                        p = role.permission_set.all().values_list("code_name")
                        permissions_list += [i[0] for i in p]

                    # 权限去重
                    permissions_list = list(set(permissions_list))

                    # 将权限列表存入redis
                    key = "user_permissions_%s"%user.id
                    redis_conn.set(key, json.dumps(permissions_list))

                    return Response({
                        "code": 200,
                        "msg": "登录成功",
                        "username": user.username,
                        "uid": user.id,
                        "token": token
                    })

                # 没有权限
                return Response({
                    "code": 206,
                    "msg": "没有管理员权限"
                })

            else:
                # 密码不正确, 判断是否重置密码
                if mobile and code:
                    # 重置密码
                    validate_sms_code = self.validate_code(redis_conn, mobile, code)
                    if validate_sms_code:
                        # 验证成功
                        user.set_password(password)
                        user.save()
                        return Response({
                            "code": 207,
                            "msg": "密码已重置"
                        })

                    else:
                        return Response({
                            "code": 204,
                            "msg": "验证码过期或者错误"
                        })

                return Response({
                    "code": 205,
                    "msg": "用户名或密码错误"
                })

        else:
            # 5.用户不存在， 第一次注册
            # 验证短信验证码
            validate_sms_code = self.validate_code(redis_conn, mobile, code)
            if validate_sms_code:
                # 短信验证通过，保存用户的信息
                user = User.objects.create_user(username=username, password=password, phone=mobile)
                user.last_login = datetime.now()
                user.save()

                return Response({
                    "code": 201,
                    "msg": "注册成功，需要申请管理员权限"
                })

            else:
                return Response({
                    "code": 204,
                    "msg": "验证码过期或者错误"
                })

    @staticmethod
    def gen_token(user):

        #  param user: 登录的用户对象
        # return token: 返回jwt token

        payload = jwt_payload_handler(user)

        token = jwt_encode_handler(payload)

        return token

    @staticmethod
    def validate_code(redis_conn, mobile, code):
        # redis_conn: redis连接对象
        # mobile:用户的手机号 ，用于获取redis中的验证码
        # code： 前端用户输入的短信验证码

        stored_code = redis_conn.get(mobile)
        if stored_code and stored_code.decode() == code:
            return True
        else:
            return False


# 统计总人数的视图
class CountUserAPIView(APIView):
    def get(self, request):

        total_count = User.objects.all().count()
        return Response({
            "code": 200,
            "total_count": total_count
        })


# 统计日增用户的视图
class DayIncrementAPIView(APIView):
    def get(self,request):
        date = time.strftime("%Y-%m-%d")
        num = User.objects.filter(date_joined__contains=date).count()

        return Response({
            "code": "200",
            "msg": '获取日增用户成功',
            "total_count": num
        })


# 统计日活跃的用户
class DayLiveAPIView(APIView):
    def get(self, request):
        date = time.strftime("%Y-%m-%d")
        num = User.objects.filter(last_login__contains=date).count()

        return Response({
            "code": "200",
            "msg": '获取日活跃用户成功',
            "total_count": num
        })

class MyPagination(PageNumberPagination):
    page_size = 2
    max_page_size = 3

    page_query_param = "page"
    page_size_query_param = "pagesize"


# 用户的视图
class UserInfoViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSer
    lookup_field = "pk"
    lookup_url_kwarg = "pk"

    pagination_class = MyPagination

    def update(self, request, *args, **kwargs):
        # 方案一 逻辑自己写
        try:
            user = self.get_object()
            user.username = request.data.get("username")
            user.set_password(request.data.get("password"))
            user.phone = request.data.get("phone")
            user.email = request.data.get("email")
            user.save()
        except:
            return Response({
                "code": 400,
                "msg": "更新用户数据，后端报错"
            })

        return Response({
            "code": 200,
            "msg": "更新用户成功"
        })

    def create(self, request, *args, **kwargs):
        # 方案一 逻辑自己写

        try:
            # 判断用户是否已存在
            User.objects.create_user(**request.data)

        except:
            return Response({
                "code": 500,
                "msg": "创建用户报错"
            })

        return Response({
            "code": 200,
            "msg": "添加用户成功"
        })


from rest_framework_jwt.utils import jwt_decode_handler
from jwt.exceptions import ExpiredSignatureError, DecodeError
import os
from django.conf import settings


# 上传头像图片的视图
class UserPortraitAPIView(APIView):
    def post(self, request):

        # 1. 直接获取前端上传的数据
        token = request.data.get("token")
        file = request.data.get("file")

        # 2. token的验证
        try:
            payload = jwt_decode_handler(token)

        except ExpiredSignatureError:
            return Response({"code": 401, "msg": "口令过期"})

        except DecodeError:
            return Response({"code": 401, "msg": "口令错误"})
        # 3.用户已登录， 可以正常上传图片
        file_name = file.name
        static_path = "static/images/users"
        abs_path = os.path.join(settings.BASE_DIR, static_path)

        # 4.判断目录不存在，创建出来
        if not os.path.exists(abs_path):
            os.makedirs(abs_path)

        # 5.拼接文件名， 打开写入二进制图片数据
        sku_image_path = os.path.join(abs_path, file_name)

        with open(sku_image_path, "wb") as f:
            f.write(file.file.read())

        # 返回响应
        return Response({
            "code": 200,
            "msg": "图片上传成功",
            "static_path": static_path
        })

    # 重写添加的方法
    def create(self, request, *args, **kwargs):
        # 获取前端数据
        avatar = request.data.get("avatar")

        str = UserPortrait.objects.filter(avatar=avatar)

        # 上传的头像存在
        if str:
            return Response({"code": 400, "msg": "头像已存在"})

        # 头像不存在
        else:
            UserPortrait.objects.create(avatar=avatar)
            return Response({"code": 200, "msg": "添加成功"})


# 七牛token的视图
from qiniu import Auth
ak = "L4KBaBkhV52xMvErYgE6XbYDh57uy2qey2qppzRe"
sk = "bildAzQKbSmdtnoAe-dUNjeqM7JMqCWaoURqbaCz"


class QiniuTokenAPIView(APIView):
    def get(self, request):
        # 生成七牛云的token
        token = self.gen_token()

        # 返回响应
        return Response({"code": 200, "token": token})

    @staticmethod
    def gen_token():
        # 实例化鉴权对象
        q = Auth(ak, sk)

        # 生成token
        token = q.upload_token("msdejx")

        # 返回响应
        return token


# 权限的视图
class PermissionViewSet(ModelViewSet):
    queryset = Permission.objects.all()
    serializer_class = PermissionSer


# 权限类型的视图
class PermissionTypeViewSet(ModelViewSet):
    queryset = PermissionType.objects.all()
    serializer_class = PermissionTypeSer












